home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Contact_Vcard_Build.php < prev    next >
PHP Script  |  2004-03-24  |  63KB  |  2,407 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */ 
  3. // +----------------------------------------------------------------------+ 
  4. // | PHP version 4                                                        | 
  5. // +----------------------------------------------------------------------+ 
  6. // | Copyright (c) 1997-2002 The PHP Group                                | 
  7. // +----------------------------------------------------------------------+ 
  8. // | This source file is subject to version 2.0 of the PHP license,       | 
  9. // | that is bundled with this package in the file LICENSE, and is        | 
  10. // | available at through the world-wide-web at                           | 
  11. // | http://www.php.net/license/2_02.txt.                                 | 
  12. // | If you did not receive a copy of the PHP license and are unable to   | 
  13. // | obtain it through the world-wide-web, please send a note to          | 
  14. // | license@php.net so we can mail you a copy immediately.               | 
  15. // +----------------------------------------------------------------------+ 
  16. // | Authors: Paul M. Jones <pjones@ciaweb.net>                           | 
  17. // +----------------------------------------------------------------------+ 
  18. // 
  19. // $Id: Contact_Vcard_Build.php,v 1.2 2004/02/02 19:09:32 pmjones Exp $ 
  20.  
  21. /**
  22. * This class builds a single vCard (version 3.0 or 2.1).
  23. *
  24. * General note: we use the terms "set" "add" and "get" as function
  25. * prefixes.
  26. * "Set" means there is only one iteration of a component, and it has
  27. * only one value repetition, so you set the whole thing at once.
  28. * "Add" means eith multiple iterations of a component are allowed, or
  29. * that there is only one iteration allowed but there can be multiple
  30. * value repetitions, so you add iterations or repetitions to the current
  31. * stack.
  32. * "Get" returns the full vCard line for a single iteration.
  33. * @author Paul M. Jones <pjones@ciaweb.net>
  34. * @package Contact_Vcard
  35. * @version 1.1
  36. */
  37.  
  38.  
  39. // Part numbers for N components
  40. define('VCARD_N_FAMILY',     0);
  41. define('VCARD_N_GIVEN',      1);
  42. define('VCARD_N_ADDL',       2);
  43. define('VCARD_N_PREFIX',     3);
  44. define('VCARD_N_SUFFIX',     4);
  45.  
  46. // Part numbers for ADR components
  47. define('VCARD_ADR_POB',      0);
  48. define('VCARD_ADR_EXTEND',   1);
  49. define('VCARD_ADR_STREET',   2);
  50. define('VCARD_ADR_LOCALITY', 3);
  51. define('VCARD_ADR_REGION',   4);
  52. define('VCARD_ADR_POSTCODE', 5);
  53. define('VCARD_ADR_COUNTRY',  6);
  54.  
  55. // Part numbers for GEO components
  56. define('VCARD_GEO_LAT',      0);
  57. define('VCARD_GEO_LON',      1);
  58.  
  59. require_once 'PEAR.php';
  60.  
  61. class Contact_Vcard_Build extends PEAR {
  62.     
  63.     
  64.     /**
  65.     * 
  66.     * Values for vCard components.
  67.     * 
  68.     * @access public
  69.     * 
  70.     * @var array
  71.     * 
  72.     */
  73.     
  74.     var $value = array();
  75.     
  76.     
  77.     /**
  78.     * 
  79.     * Parameters for vCard components.
  80.     * 
  81.     * @access public
  82.     * 
  83.     * @var array
  84.     * 
  85.     */
  86.     
  87.     var $param = array();
  88.     
  89.     
  90.     /**
  91.     *
  92.     * Tracks which component (N, ADR, TEL, etc) value was last set or added.
  93.     * Used when adding parameters automatically to the proper component.
  94.     *
  95.     * @access public
  96.     * 
  97.     * @var string
  98.     *
  99.     */
  100.     
  101.     var $autoparam = null;
  102.     
  103.     
  104.     /**
  105.     *
  106.     * Constructor.
  107.     *
  108.     * @access public
  109.     * 
  110.     * @param string $version The vCard version to build; affects which
  111.     * parameters are allowed and which components are returned by
  112.     * fetch().
  113.     * 
  114.     * @return void
  115.     * 
  116.     * @see Contact_Vcard_Build::fetch()
  117.     *
  118.     */
  119.     
  120.     function Contact_Vcard_Build($version = '3.0')
  121.     {
  122.         $this->PEAR();
  123.         $this->setErrorHandling(PEAR_ERROR_PRINT);
  124.         $this->setVersion($version);
  125.     }
  126.     
  127.     
  128.     /**
  129.     * 
  130.     * Prepares a string so it may be safely used as vCard values.  DO
  131.     * NOT use this with binary encodings.  Operates on text in-place;
  132.     * does not return a value.  Recursively descends into arrays.
  133.     * 
  134.     * Escapes a string so that...
  135.     *     ; => \;
  136.     *     , => \,
  137.     *     newline => literal \n
  138.     * 
  139.     * @access public
  140.     * 
  141.     * @param mixed $text The string or array or strings to escape.
  142.     * 
  143.     * @return mixed Void on success, or a PEAR_Error object on failure.
  144.     * 
  145.     */
  146.     
  147.     function escape(&$text)
  148.     {
  149.         if (is_object($text)) {
  150.         
  151.             return $this->raiseError('The escape() method works only with string literals and arrays.');
  152.         
  153.         } elseif (is_array($text)) {
  154.             
  155.             foreach ($text as $key => $val) {
  156.                 $this->escape($val);
  157.                 $text[$key] = $val;
  158.             }
  159.             
  160.         } else {
  161.         
  162.             // escape semicolons not led by a backslash
  163.             $regex = '(?<!\\\\)(\;)';
  164.             $text = preg_replace("/$regex/i", "\\;", $text);
  165.             
  166.             // escape commas not led by a backslash
  167.             $regex = '(?<!\\\\)(\,)';
  168.             $text = preg_replace("/$regex/i", "\\,", $text);
  169.             
  170.             // escape newlines
  171.             $regex = '\\n';
  172.             $text = preg_replace("/$regex/i", "\\n", $text);
  173.             
  174.         }
  175.     }
  176.     
  177.     
  178.     /**
  179.     * 
  180.     * Adds a parameter value for a given component and parameter name.
  181.     *
  182.     * Note that although vCard 2.1 allows you to specify a parameter
  183.     * value without a name (e.g., "HOME" instead of "TYPE=HOME") this
  184.     * class is not so lenient.  ;-)    You must specify a parameter name
  185.     * (TYPE, ENCODING, etc) when adding a parameter.  Call multiple
  186.     * times if you want to add multiple values to the same parameter.
  187.     * E.g.:
  188.     * 
  189.     * $vcard = new Contact_Vcard_Build();
  190.     *
  191.     * // set "TYPE=HOME,PREF" for the first TEL component
  192.     * $vcard->addParam('TEL', 0, 'TYPE', 'HOME');
  193.     * $vcard->addParam('TEL', 0, 'TYPE', 'PREF');
  194.     * 
  195.     * @access public
  196.     * 
  197.     * @param string $param_name The parameter name, such as TYPE, VALUE,
  198.     * or ENCODING.
  199.     * 
  200.     * @param string $param_value The parameter value.
  201.     * 
  202.     * @param string $comp The vCard component for which this is a
  203.     * paramter (ADR, TEL, etc).  If null, will be the component that was
  204.     * last set or added-to.
  205.     * 
  206.     * @param mixed $iter An integer vCard component iteration that this
  207.     * is a param for.  E.g., if you have more than one ADR component, 0
  208.     * refers to the first ADR, 1 to the second ADR, and so on.  If null,
  209.     * the parameter will be added to the last component iteration
  210.     * available.
  211.     * 
  212.     * @return mixed Void on success, or a PEAR_Error object on failure.
  213.     * 
  214.     */
  215.     
  216.     function addParam($param_name, $param_value, $comp = null,
  217.         $iter = null)
  218.     {
  219.         // if component is not specified, default to the last component
  220.         // that was set or added.
  221.         if ($comp === null) {
  222.             $comp = $this->autoparam;
  223.         }
  224.         
  225.         // using a null iteration means the param should be associated
  226.         // with the latest/most-recent iteration of the selected
  227.         // component.
  228.         if ($iter === null) {
  229.             $iter = $this->countIter($comp) - 1;
  230.         }
  231.         
  232.         // massage the text arguments
  233.         $comp = strtoupper(trim($comp));
  234.         $param_name = strtoupper(trim($param_name));
  235.         $param_value = trim($param_value);
  236.         
  237.         if (! is_integer($iter) || $iter < 0) {
  238.         
  239.             return $this->raiseError("$iter is not a valid iteration number for $comp; must be a positive integer.");
  240.             
  241.         } else {
  242.             
  243.             $result = $this->validateParam($param_name, $param_value, $comp, $iter);
  244.             
  245.             if (PEAR::isError($result)) {
  246.                 return $result;
  247.             } else {
  248.                 $this->param[$comp][$iter][$param_name][] = $param_value;
  249.             }
  250.             
  251.         }
  252.     }
  253.     
  254.     
  255.     /**
  256.     * 
  257.     * Validates parameter names and values based on the vCard version
  258.     * (2.1 or 3.0).
  259.     * 
  260.     * @access public
  261.     * 
  262.     * @param string $name The parameter name (e.g., TYPE or ENCODING).
  263.     * 
  264.     * @param string $text The parameter value (e.g., HOME or BASE64).
  265.     * 
  266.     * @param string $comp Optional, the component name (e.g., ADR or
  267.     * PHOTO).  Only used for error messaging.
  268.     * 
  269.     * @param string $iter Optional, the iteration of the component. 
  270.     * Only used for error messaging.
  271.     * 
  272.     * @return mixed Boolean true if the parameter is valid, or a
  273.     * PEAR_Error object if not.
  274.     * 
  275.     */
  276.     
  277.     function validateParam($name, $text, $comp = null, $iter = null)
  278.     {
  279.         $name = strtoupper($name);
  280.         $text = strtoupper($text);
  281.         
  282.         // all param values must have only the characters A-Z 0-9 and -.
  283.         if (preg_match('/[^a-zA-Z0-9\-]/i', $text)) {
  284.             
  285.             $result = $this->raiseError("vCard [$comp] [$iter] [$name]: The parameter value may contain only a-z, A-Z, 0-9, and dashes (-).");
  286.         
  287.         } elseif ($this->value['VERSION'][0][0][0] == '2.1') {
  288.             
  289.             // Validate against version 2.1 (pretty strict)
  290.             
  291.             $types = array (
  292.                 'DOM', 'INTL', 'POSTAL', 'PARCEL','HOME', 'WORK',
  293.                 'PREF', 'VOICE', 'FAX', 'MSG', 'CELL', 'PAGER',
  294.                 'BBS', 'MODEM', 'CAR', 'ISDN', 'VIDEO',
  295.                 'AOL', 'APPLELINK', 'ATTMAIL', 'CIS', 'EWORLD',
  296.                 'INTERNET', 'IBMMAIL', 'MCIMAIL',
  297.                 'POWERSHARE', 'PRODIGY', 'TLX', 'X400',
  298.                 'GIF', 'CGM', 'WMF', 'BMP', 'MET', 'PMB', 'DIB',
  299.                 'PICT', 'TIFF', 'PDF', 'PS', 'JPEG', 'QTIME',
  300.                 'MPEG', 'MPEG2', 'AVI',
  301.                 'WAVE', 'AIFF', 'PCM',
  302.                 'X509', 'PGP'
  303.             );
  304.             
  305.             
  306.             switch ($name) {
  307.             
  308.             case 'TYPE':
  309.                 if (! in_array($text, $types)) {
  310.                     $result = $this->raiseError("vCard 2.1 [$comp] [$iter]: $text is not a recognized TYPE.");
  311.                 } else {
  312.                     $result = true;
  313.                 }
  314.                 break;
  315.             
  316.             case 'ENCODING':
  317.                 if ($text != '7BIT' &&
  318.                     $text != '8BIT' &&
  319.                     $text != 'BASE64' &&
  320.                     $text != 'QUOTED-PRINTABLE') {
  321.                     $result = $this->raiseError("vCard 2.1 [$comp] [$iter]: $text is not a recognized ENCODING.");
  322.                 } else {
  323.                     $result = true;
  324.                 }
  325.                 break;
  326.             
  327.             case 'CHARSET':
  328.                 // all charsets are OK
  329.                 $result = true;
  330.                 break;
  331.                 
  332.             case 'LANGUAGE':
  333.                 // all languages are OK
  334.                 $result = true;
  335.                 break;
  336.             
  337.             case 'VALUE':
  338.                 if ($text != 'INLINE' &&
  339.                     $text != 'CONTENT-ID' &&
  340.                     $text != 'CID' &&
  341.                     $text != 'URL' &&
  342.                     $text != 'VCARD') {
  343.                     $result = $this->raiseError("vCard 2.1 [$comp] [$iter]: $text is not a recognized VALUE.");
  344.                 } else {
  345.                     $result = true;
  346.                 }
  347.                 break;
  348.                 
  349.             default:
  350.                 $result = $this->raiseError("vCard 2.1 [$comp] [$iter]: $name is an unknown or invalid parameter name.");
  351.                 break;
  352.             }
  353.             
  354.         } elseif ($this->value['VERSION'][0][0][0] == '3.0') {
  355.             
  356.             // Validate against version 3.0 (pretty lenient)
  357.             
  358.             switch ($name) {
  359.             
  360.             case 'TYPE':
  361.                 // all types are OK
  362.                 $result = true;
  363.                 break;
  364.                 
  365.             case 'LANGUAGE':
  366.                 // all languages are OK
  367.                 $result = true;
  368.                 break;
  369.             
  370.             case 'ENCODING':
  371.                 if ($text != '8BIT' &&
  372.                     $text != 'B') {
  373.                     $result = $this->raiseError("vCard 3.0 [$comp] [$iter]: The only allowed ENCODING parameters are 8BIT and B.");
  374.                 } else {
  375.                     $result = true;
  376.                 }
  377.                 break;
  378.             
  379.             case 'VALUE':
  380.                 if ($text != 'BINARY' &&
  381.                     $text != 'PHONE-NUMBER' &&
  382.                     $text != 'TEXT' &&
  383.                     $text != 'URI' &&
  384.                     $text != 'UTC-OFFSET' &&
  385.                     $text != 'VCARD') {
  386.                     $result = $this->raiseError("vCard 3.0 [$comp] [$iter]: The only allowed VALUE parameters are BINARY, PHONE-NUMBER, TEXT, URI, UTC-OFFSET, and VCARD.");
  387.                 } else {
  388.                     $result = true;
  389.                 }
  390.                 break;
  391.             
  392.             default:
  393.                 $result = $this->raiseError("vCard 3.0 [$comp] [$iter]: Unknown or invalid parameter name ($name).");
  394.                 break;
  395.                 
  396.             }
  397.             
  398.         } else {
  399.         
  400.             $result = $this->raiseError("[$comp] [$iter] Unknown vCard version number or other error.");
  401.         
  402.         }
  403.         
  404.         return $result;
  405.             
  406.     }
  407.     
  408.     
  409.     /**
  410.     * 
  411.     * Gets back the parameter string for a given component.
  412.     * 
  413.     * @access public
  414.     * 
  415.     * @param string $comp The component to get parameters for (ADR, TEL,
  416.     * etc).
  417.     * 
  418.     * @param int $iter The vCard component iteration to get the param
  419.     * list for.  E.g., if you have more than one ADR component, 0 refers
  420.     * to the first ADR, 1 to the second ADR, and so on.
  421.     * 
  422.     * @return string
  423.     * 
  424.     */
  425.     
  426.     function getParam($comp, $iter = 0)
  427.     {
  428.         $comp = strtoupper($comp);
  429.         $text = '';
  430.         
  431.         if (isset($this->param[$comp][$iter]) &&
  432.             is_array($this->param[$comp][$iter])) {
  433.             
  434.             // loop through the array of parameters for
  435.             // the component
  436.             
  437.             foreach ($this->param[$comp][$iter] as $param_name => $param_val) {
  438.                 
  439.                 // if there were previous parameter names, separate with
  440.                 // a semicolon
  441.                 if ($text != '') {
  442.                     $text .= ';';
  443.                 }
  444.                 
  445.                 if ($param_val === null) {
  446.                     
  447.                     // no parameter value was specified, which is typical
  448.                     // for vCard version 2.1 -- the name is the value.
  449.                     $this->escape($param_name);
  450.                     $text .= $param_name;
  451.                     
  452.                 } else {
  453.                     // set the parameter name...
  454.                     $text .= strtoupper($param_name) . '=';
  455.                     
  456.                     // ...then escape and comma-separate the parameter
  457.                     // values.
  458.                     $this->escape($param_val);
  459.                     $text .= implode(',', $param_val);
  460.                 }
  461.             }
  462.         }
  463.         
  464.         // if there were no parameters, this will be blank.
  465.         return $text;
  466.     }
  467.     
  468.     
  469.     /**
  470.     * 
  471.     * Resets the vCard values and params to be blank.
  472.     * 
  473.     * @access public
  474.     * 
  475.     * @param string $version The vCard version to reset to ('2.1' or
  476.     * '3.0' -- default is the same version as previously set).
  477.     * 
  478.     * @return void
  479.     * 
  480.     */
  481.     
  482.     function reset($version = null)
  483.     {
  484.         $prev = $this->value['VERSION'][0][0][0];
  485.         
  486.         $this->value = array();
  487.         $this->param = array();
  488.         $this->autoparam = null;
  489.         
  490.         if ($version === null) {
  491.             $this->setVersion($prev);
  492.         } else {
  493.             $this->setVersion($version);
  494.         }
  495.     }
  496.     
  497.     
  498.     /**
  499.     * 
  500.     * Gets the left-side/prefix/before-the-colon (metadata) part of a
  501.     * vCard line, including the component identifier, the parameter
  502.     * list, and a colon.
  503.     * 
  504.     * @access public
  505.     * 
  506.     * @param string $comp The component to get metadata for (ADR, TEL,
  507.     * etc).
  508.     * 
  509.     * @param int $iter The vCard component iteration to get the metadata
  510.     * for.  E.g., if you have more than one ADR component, 0 refers to
  511.     * the first ADR, 1 to the second ADR, and so on.
  512.     * 
  513.     * @return string The line prefix metadata.
  514.     * 
  515.     */
  516.     
  517.     function getMeta($comp, $iter = 0)
  518.     {
  519.         $params = $this->getParam($comp, $iter);
  520.         
  521.         if (trim($params) == '') {
  522.             // no parameters
  523.             $text = $comp . ':';
  524.         } else {
  525.             // has parameters.  put an extra semicolon in.
  526.             $text = $comp . ';' . $params . ':';
  527.         }
  528.         
  529.         return $text;
  530.     }
  531.     
  532.     
  533.     /**
  534.     *
  535.     * Generic, all-purpose method to store a string or array in
  536.     * $this->value, in a way suitable for later output as a vCard
  537.     * element.  This forces the value to be the passed text or array
  538.     * value, overriding any prior values.
  539.     * 
  540.     * @access public
  541.     *
  542.     * @param string $comp The component to set the value for ('N',
  543.     * 'ADR', etc).
  544.     * 
  545.     * @param int $iter The component-iteration to set the value for.
  546.     * 
  547.     * @param int $part The part number of the component-iteration to set
  548.     * the value for.
  549.     * 
  550.     * @param mixed $text A string or array; the set of repeated values
  551.     * for this component-iteration part.
  552.     * 
  553.     * @return void
  554.     * 
  555.     */
  556.     
  557.     function setValue($comp, $iter, $part, $text)
  558.     {
  559.         $comp = strtoupper($comp);
  560.         settype($text, 'array');
  561.         $this->value[$comp][$iter][$part] = $text;
  562.         $this->autoparam = $comp;
  563.     }
  564.     
  565.     
  566.     /**
  567.     *
  568.     * Generic, all-purpose method to add a repetition of a string or
  569.     * array in $this->value, in a way suitable for later output as a
  570.     * vCard element.  This appends the value to be the passed text or
  571.     * array value, leaving any prior values in place.
  572.     * 
  573.     * @access public
  574.     *
  575.     * @param string $comp The component to set the value for ('N',
  576.     * 'ADR', etc).
  577.     * 
  578.     * @param int $iter The component-iteration to set the value for.
  579.     * 
  580.     * @param int $part The part number of the component-iteration to set
  581.     * the value for.
  582.     * 
  583.     * @param mixed $text A string or array; the set of repeated values
  584.     * for this component-iteration part.
  585.     * 
  586.     * @return void
  587.     * 
  588.     */
  589.     
  590.     function addValue($comp, $iter, $part, $text)
  591.     {
  592.         $comp = strtoupper($comp);
  593.         settype($text, 'array');
  594.         foreach ($text as $val) {
  595.             $this->value[$comp][$iter][$part][] = $val;
  596.         }
  597.         $this->autoparam = $comp;
  598.     }
  599.     
  600.     
  601.     /**
  602.     *
  603.     * Generic, all-purpose method to get back the data stored in $this->value.
  604.     * 
  605.     * @access public
  606.     *
  607.     * @param string $comp The component to set the value for ('N',
  608.     * 'ADR', etc).
  609.     * 
  610.     * @param int $iter The component-iteration to set the value for.
  611.     * 
  612.     * @param int $part The part number of the component-iteration to get
  613.     * the value for.
  614.     * 
  615.     * @param mixed $rept The repetition number within the part to get;
  616.     * if null, get all repetitions of the part within the iteration.
  617.     * 
  618.     * @return string The value, escaped and delimited, of all
  619.     * repetitions in the component-iteration part (or specific
  620.     * repetition within the part).
  621.     * 
  622.     */
  623.     
  624.     function getValue($comp, $iter = 0, $part = 0, $rept = null)
  625.     {
  626.         if ($rept === null &&
  627.             is_array($this->value[$comp][$iter][$part]) ) {
  628.             
  629.             // get all repetitions of a part
  630.             $list = array();
  631.             foreach ($this->value[$comp][$iter][$part] as $key => $val) {
  632.                 $list[] = trim($val);
  633.             }
  634.             
  635.             $this->escape($list);
  636.             return implode(',', $list);
  637.             
  638.         } else {
  639.             
  640.             // get a specific repetition of a part
  641.             $text = trim($this->value[$comp][$iter][$part][$rept]);
  642.             $this->escape($text);
  643.             return $text;
  644.             
  645.         }
  646.     }
  647.     
  648.     
  649.     /**
  650.     * 
  651.     * Sets the full N component of the vCard.  Will replace all other
  652.     * values.  There can only be one N component per vCard.
  653.     * 
  654.     * @access public
  655.     * 
  656.     * @param mixed $family Single (string) or multiple (array)
  657.     * family/last name.
  658.     * 
  659.     * @param mixed $given Single (string) or multiple (array)
  660.     * given/first name.
  661.     * 
  662.     * @param mixed $addl Single (string) or multiple (array)
  663.     * additional/middle name.
  664.     * 
  665.     * @param mixed $prefix Single (string) or multiple (array) honorific
  666.     * prefix such as Mr., Miss, etc.
  667.     * 
  668.     * @param mixed $suffix Single (string) or multiple (array) honorific
  669.     * suffix such as III, Jr., Ph.D., etc.
  670.     * 
  671.     * @return void
  672.     * 
  673.     */
  674.     
  675.     function setName($family, $given, $addl, $prefix, $suffix)
  676.     {
  677.         $this->autoparam = 'N';
  678.         $this->setValue('N', 0, VCARD_N_FAMILY, $family);
  679.         $this->setValue('N', 0, VCARD_N_GIVEN, $given);
  680.         $this->setValue('N', 0, VCARD_N_ADDL, $addl);
  681.         $this->setValue('N', 0, VCARD_N_PREFIX, $prefix);
  682.         $this->setValue('N', 0, VCARD_N_SUFFIX, $suffix);
  683.     }
  684.     
  685.     
  686.     /**
  687.     * 
  688.     * Gets back the full N component (first iteration only, since there
  689.     * can only be one N component per vCard).
  690.     * 
  691.     * @access public
  692.     * 
  693.     * @return string The first N component-interation of the vCard.
  694.     * 
  695.     */
  696.     
  697.     function getName()
  698.     {
  699.         return $this->getMeta('N', 0) .
  700.             $this->getValue('N', 0, VCARD_N_FAMILY) . ';' .
  701.             $this->getValue('N', 0, VCARD_N_GIVEN) . ';' .
  702.             $this->getValue('N', 0, VCARD_N_ADDL) . ';' .
  703.             $this->getValue('N', 0, VCARD_N_PREFIX) . ';' .
  704.             $this->getValue('N', 0, VCARD_N_SUFFIX);
  705.     }
  706.     
  707.     
  708.     
  709.     /**
  710.     * 
  711.     * Sets the FN component of the card.  If no text is passed as the
  712.     * FN value, constructs an FN automatically from N components.  There
  713.     * is only one FN iteration per vCard.
  714.     * 
  715.     * @access public
  716.     * 
  717.     * @param string $text Override the automatic generation of FN from N
  718.     * elements with the specified text.
  719.     * 
  720.     * @return mixed Void on success, or a PEAR_Error object on failure.
  721.     * 
  722.     */
  723.     
  724.     function setFormattedName($text = null)
  725.     {
  726.         $this->autoparam = 'FN';
  727.         
  728.         if ($text === null) {
  729.             
  730.             // no text was specified for the FN, so build it
  731.             // from the current N components if an N exists
  732.             if (is_array($this->value['N'])) {
  733.                 
  734.                 // build from N.
  735.                 // first (given) name, first iteration, first repetition
  736.                 $text .= $this->getValue('N', 0, VCARD_N_GIVEN, 0);
  737.             
  738.                 // add a space after, if there was text
  739.                 if ($text != '') {
  740.                     $text .= ' ';
  741.                 }
  742.                 
  743.                 // last (family) name, first iteration, first repetition
  744.                 $text .= $this->getValue('N', 0, VCARD_N_FAMILY, 0);
  745.                 
  746.                 // add a space after, if there was text
  747.                 if ($text != '') {
  748.                     $text .= ' ';
  749.                 }
  750.                 
  751.                 // last-name suffix, first iteration, first repetition
  752.                 $text .= $this->getValue('N', 0, VCARD_N_SUFFIX, 0);
  753.                 
  754.                 
  755.             } else {
  756.                 
  757.                 // no N exists, and no FN was set, so return.
  758.                 return $this->raiseError('FN not specified and N not set; cannot set FN.');
  759.                 
  760.             }
  761.         
  762.         }
  763.         
  764.         $this->setValue('FN', 0, 0, $text);
  765.         
  766.     }
  767.     
  768.     
  769.     /**
  770.     * 
  771.     * Gets back the full FN component value.  Only ever returns iteration
  772.     * zero, because only one FN component is allowed per vCard.
  773.     * 
  774.     * @access public
  775.     * 
  776.     * @return string The FN value of the vCard.
  777.     * 
  778.     */
  779.     
  780.     function getFormattedName()
  781.     {
  782.         return $this->getMeta('FN', 0) . $this->getValue('FN', 0, 0);
  783.     }
  784.     
  785.     
  786.     /**
  787.     * 
  788.     * Sets the version of the the vCard.  Only one iteration.
  789.     * 
  790.     * @access public
  791.     * 
  792.     * @param string $text The text value of the verson text ('3.0' or '2.1').
  793.     * 
  794.     * @return mixed Void on success, or a PEAR_Error object on failure.
  795.     * 
  796.     */
  797.     
  798.     function setVersion($text = '3.0')
  799.     {
  800.         $this->autoparam = 'VERSION';
  801.         if ($text != '3.0' && $text != '2.1') {
  802.             return $this->raiseError('Version must be 3.0 or 2.1 to be valid.');
  803.         } else {
  804.             $this->setValue('VERSION', 0, 0, $text);
  805.         }
  806.     }
  807.     
  808.     
  809.     /**
  810.     * 
  811.     * Gets back the version of the the vCard.  Only one iteration.
  812.     * 
  813.     * @access public
  814.     * 
  815.     * @return string The data-source of the vCard.
  816.     * 
  817.     */
  818.     
  819.     function getVersion()
  820.     {
  821.         return $this->getMeta('VERSION', 0) .
  822.             $this->getValue('VERSION', 0);
  823.     }
  824.     
  825.     
  826.     /**
  827.     * 
  828.     * Sets the data-source of the the vCard.  Only one iteration.
  829.     * 
  830.     * @access public
  831.     * 
  832.     * @param string $text The text value of the data-source text.
  833.     * 
  834.     * @return void
  835.     * 
  836.     */
  837.     
  838.     function setSource($text)
  839.     {
  840.         $this->autoparam = 'SOURCE';
  841.         $this->setValue('SOURCE', 0, 0, $text);
  842.     }
  843.     
  844.     
  845.     /**
  846.     * 
  847.     * Gets back the data-source of the the vCard.  Only one iteration.
  848.     * 
  849.     * @access public
  850.     * 
  851.     * @return string The data-source of the vCard.
  852.     * 
  853.     */
  854.     
  855.     function getSource()
  856.     {
  857.         return $this->getMeta('SOURCE', 0) .
  858.             $this->getValue('SOURCE', 0, 0);
  859.     }
  860.     
  861.     
  862.     /**
  863.     * 
  864.     * Sets the displayed name of the vCard data-source.  Only one iteration.
  865.     * If no name is specified, copies the value of SOURCE.
  866.     * 
  867.     * @access public
  868.     * 
  869.     * @param string $text The text value of the displayed data-source
  870.     * name.  If null, copies the value of SOURCE.
  871.     * 
  872.     * @return mixed Void on success, or a PEAR_Error object on failure.
  873.     * 
  874.     */
  875.     
  876.     function setSourceName($text = null)
  877.     {
  878.         $this->autoparam = 'NAME';
  879.         
  880.         if ($text === null) {
  881.             if (is_array($this->value['SOURCE'])) {
  882.                 $text = $this->getValue('SOURCE', 0, 0);
  883.             } else {
  884.                 return $this->raiseError('NAME not specified and SOURCE not set; cannot set NAME.');
  885.             }
  886.         }
  887.         
  888.         $this->setValue('NAME', 0, 0, $text);
  889.     }
  890.     
  891.     
  892.     /**
  893.     * 
  894.     * Gets back the displayed data-source name of the the vCard.  Only
  895.     * one iteration.
  896.     * 
  897.     * @access public
  898.     * 
  899.     * @return string The data-source name of the vCard.
  900.     * 
  901.     */
  902.     
  903.     function getSourceName()
  904.     {
  905.         return $this->getMeta('NAME', 0) .
  906.             $this->getValue('NAME', 0, 0);
  907.     }
  908.     
  909.     
  910.     
  911.     
  912.     /**
  913.     * 
  914.     * Sets the value of the PHOTO component.  There is only one allowed
  915.     * per vCard.
  916.     *
  917.     * @access public
  918.     * 
  919.     * @param string $text The value to set for this component.
  920.     *
  921.     * @return void
  922.     * 
  923.     */
  924.     
  925.     function setPhoto($text)
  926.     {
  927.         $this->autoparam = 'PHOTO';
  928.         $this->setValue('PHOTO', 0, 0, $text);
  929.     }
  930.     
  931.     
  932.     
  933.     /**
  934.     * 
  935.     * Gets back the value of the PHOTO component.  There is only one
  936.     * allowed per vCard.
  937.     *
  938.     * @access public
  939.     * 
  940.     * @return string The value of this component.
  941.     * 
  942.     */
  943.     
  944.     function getPhoto()
  945.     {
  946.         return $this->getMeta('PHOTO') .
  947.             $this->getValue('PHOTO', 0, 0);
  948.     }
  949.     
  950.     
  951.     
  952.     
  953.     /**
  954.     * 
  955.     * Sets the value of the LOGO component.  There is only one allowed
  956.     * per vCard.
  957.     *
  958.     * @access public
  959.     * 
  960.     * @param string $text The value to set for this component.
  961.     *
  962.     * @return void
  963.     * 
  964.     */
  965.     
  966.     function setLogo($text)
  967.     {
  968.         $this->autoparam = 'LOGO';
  969.         $this->setValue('LOGO', 0, 0, $text);
  970.     }
  971.     
  972.     
  973.     
  974.     /**
  975.     * 
  976.     * Gets back the value of the LOGO component.  There is only one
  977.     * allowed per vCard.
  978.     *
  979.     * @access public
  980.     * 
  981.     * @return string The value of this component.
  982.     * 
  983.     */
  984.     
  985.     function getLogo()
  986.     {
  987.         return $this->getMeta('LOGO') . $this->getValue('LOGO', 0, 0);
  988.     }
  989.     
  990.     
  991.     
  992.     /**
  993.     * 
  994.     * Sets the value of the SOUND component.  There is only one allowed
  995.     * per vCard.
  996.     *
  997.     * @access public
  998.     * 
  999.     * @param string $text The value to set for this component.
  1000.     *
  1001.     * @return void
  1002.     * 
  1003.     */
  1004.     
  1005.     function setSound($text)
  1006.     {
  1007.         $this->autoparam = 'SOUND';
  1008.         $this->setValue('SOUND', 0, 0, $text);
  1009.     }
  1010.     
  1011.     
  1012.     /**
  1013.     * 
  1014.     * Gets back the value of the SOUND component.  There is only one
  1015.     * allowed per vCard.
  1016.     *
  1017.     * @access public
  1018.     * 
  1019.     * @return string The value of this component.
  1020.     * 
  1021.     */
  1022.     
  1023.     function getSound()
  1024.     {
  1025.         return $this->getMeta('SOUND') .
  1026.             $this->getValue('SOUND', 0, 0);
  1027.     }
  1028.     
  1029.     
  1030.     /**
  1031.     * 
  1032.     * Sets the value of the KEY component.  There is only one allowed
  1033.     * per vCard.
  1034.     *
  1035.     * @access public
  1036.     * 
  1037.     * @param string $text The value to set for this component.
  1038.     *
  1039.     * @return void
  1040.     * 
  1041.     */
  1042.     
  1043.     function setKey($text)
  1044.     {
  1045.         $this->autoparam = 'KEY';
  1046.         $this->setValue('KEY', 0, 0, $text);
  1047.     }
  1048.     
  1049.     
  1050.     
  1051.     /**
  1052.     * 
  1053.     * Gets back the value of the KEY component.  There is only one
  1054.     * allowed per vCard.
  1055.     *
  1056.     * @access public
  1057.     * 
  1058.     * @return string The value of this component.
  1059.     * 
  1060.     */
  1061.     
  1062.     function getKey()
  1063.     {
  1064.         return $this->getMeta('KEY') . $this->getValue('KEY', 0, 0);
  1065.     }
  1066.     
  1067.     
  1068.     /**
  1069.     * 
  1070.     * Sets the value of the BDAY component.  There is only one allowed
  1071.     * per vCard. Date format is "yyyy-mm-dd[Thh:ii[:ss[Z|-06:00]]]".
  1072.     *
  1073.     * @access public
  1074.     * 
  1075.     * @param string $text The value to set for this component.
  1076.     *
  1077.     * @return void
  1078.     * 
  1079.     */
  1080.     
  1081.     
  1082.     function setBirthday($text)
  1083.     {
  1084.         $this->autoparam = 'BDAY';
  1085.         $this->setValue('BDAY', 0, 0, $text);
  1086.     }
  1087.     
  1088.     
  1089.     /**
  1090.     * 
  1091.     * Gets back the value of the BDAY component.  There is only one
  1092.     * allowed per vCard.
  1093.     *
  1094.     * @access public
  1095.     * 
  1096.     * @return string The value of this component.
  1097.     * 
  1098.     */
  1099.     
  1100.     function getBirthday()
  1101.     {
  1102.         return $this->getMeta('BDAY') . $this->getValue('BDAY', 0, 0);
  1103.     }
  1104.     
  1105.     
  1106.     /**
  1107.     * 
  1108.     * Sets the value of the TZ component.  There is only one allowed per
  1109.     * vCard.
  1110.     *
  1111.     * @access public
  1112.     * 
  1113.     * @param string $text The value to set for this component.
  1114.     *
  1115.     * @return void
  1116.     * 
  1117.     */
  1118.     
  1119.     function setTZ($text)
  1120.     {
  1121.         $this->autoparam = 'TZ';
  1122.         $this->setValue('TZ', 0, 0, $text);
  1123.     }
  1124.     
  1125.     
  1126.     /**
  1127.     * 
  1128.     * Gets back the value of the TZ component.  There is only one
  1129.     * allowed per vCard.
  1130.     *
  1131.     * @access public
  1132.     * 
  1133.     * @return string The value of this component.
  1134.     * 
  1135.     */
  1136.     
  1137.     function getTZ()
  1138.     {
  1139.         return $this->getMeta('TZ') . $this->getValue('TZ', 0, 0);
  1140.     }
  1141.     
  1142.     
  1143.     /**
  1144.     * 
  1145.     * Sets the value of the MAILER component.  There is only one allowed
  1146.     * per vCard.
  1147.     *
  1148.     * @access public
  1149.     * 
  1150.     * @param string $text The value to set for this component.
  1151.     *
  1152.     * @return void
  1153.     * 
  1154.     */
  1155.     
  1156.     function setMailer($text)
  1157.     {
  1158.         $this->autoparam = 'MAILER';
  1159.         $this->setValue('MAILER', 0, 0, $text);
  1160.     }
  1161.     
  1162.     
  1163.     /**
  1164.     * 
  1165.     * Gets back the value of the MAILER component.  There is only one
  1166.     * allowed per vCard.
  1167.     *
  1168.     * @access public
  1169.     * 
  1170.     * @return string The value of this component.
  1171.     * 
  1172.     */
  1173.     
  1174.     function getMailer()
  1175.     {
  1176.         return $this->getMeta('MAILER') .
  1177.             $this->getValue('MAILER', 0, 0);
  1178.     }
  1179.     
  1180.     /**
  1181.     * 
  1182.     * Sets the value of the NOTE component.  There is only one allowed
  1183.     * per vCard.
  1184.     *
  1185.     * @access public
  1186.     * 
  1187.     * @param string $text The value to set for this component.
  1188.     *
  1189.     * @return void
  1190.     * 
  1191.     */
  1192.     
  1193.     function setNote($text)
  1194.     {
  1195.         $this->autoparam = 'NOTE';
  1196.         $this->setValue('NOTE', 0, 0, $text);
  1197.     }
  1198.     
  1199.     
  1200.     /**
  1201.     * 
  1202.     * Gets back the value of the NOTE component.  There is only one
  1203.     * allowed per vCard.
  1204.     *
  1205.     * @access public
  1206.     * 
  1207.     * @return string The value of this component.
  1208.     * 
  1209.     */
  1210.     
  1211.     function getNote()
  1212.     {
  1213.         return $this->getMeta('NOTE') . $this->getValue('NOTE', 0, 0);
  1214.     }
  1215.     
  1216.     
  1217.     /**
  1218.     * 
  1219.     * Sets the value of the TITLE component.  There is only one allowed
  1220.     * per vCard.
  1221.     *
  1222.     * @access public
  1223.     * 
  1224.     * @param string $text The value to set for this component.
  1225.     *
  1226.     * @return void
  1227.     * 
  1228.     */
  1229.     
  1230.     function setTitle($text)
  1231.     {
  1232.         $this->autoparam = 'TITLE';
  1233.         $this->setValue('TITLE', 0, 0, $text);
  1234.     }
  1235.     
  1236.     
  1237.     /**
  1238.     * 
  1239.     * Gets back the value of the TITLE component.  There is only one
  1240.     * allowed per vCard.
  1241.     *
  1242.     * @access public
  1243.     * 
  1244.     * @return string The value of this component.
  1245.     * 
  1246.     */
  1247.     
  1248.     function getTitle()
  1249.     {
  1250.         return $this->getMeta('TITLE') .
  1251.             $this->getValue('TITLE', 0, 0);
  1252.     }
  1253.     
  1254.     
  1255.     /**
  1256.     * 
  1257.     * Sets the value of the ROLE component.  There is only one allowed
  1258.     * per vCard.
  1259.     *
  1260.     * @access public
  1261.     * 
  1262.     * @param string $text The value to set for this component.
  1263.     *
  1264.     * @return void
  1265.     * 
  1266.     */
  1267.     
  1268.     function setRole($text)
  1269.     {
  1270.         $this->autoparam = 'ROLE';
  1271.         $this->setValue('ROLE', 0, 0, $text);
  1272.     }
  1273.     
  1274.     
  1275.     /**
  1276.     * 
  1277.     * Gets back the value of the ROLE component.  There is only one
  1278.     * allowed per vCard.
  1279.     *
  1280.     * @access public
  1281.     * 
  1282.     * @return string The value of this component.
  1283.     * 
  1284.     */
  1285.     
  1286.     function getRole()
  1287.     {
  1288.         return $this->getMeta('ROLE') . $this->getValue('ROLE', 0, 0);
  1289.     }
  1290.     
  1291.     
  1292.     
  1293.     
  1294.     /**
  1295.     * 
  1296.     * Sets the value of the URL component.  There is only one allowed
  1297.     * per vCard.
  1298.     *
  1299.     * @access public
  1300.     * 
  1301.     * @param string $text The value to set for this component.
  1302.     *
  1303.     * @return void
  1304.     * 
  1305.     */
  1306.     
  1307.     function setURL($text)
  1308.     {
  1309.         $this->autoparam = 'URL';
  1310.         $this->setValue('URL', 0, 0, $text);
  1311.     }
  1312.     
  1313.     
  1314.     /**
  1315.     * 
  1316.     * Gets back the value of the URL component.  There is only one
  1317.     * allowed per vCard.
  1318.     *
  1319.     * @access public
  1320.     * 
  1321.     * @return string The value of this component.
  1322.     * 
  1323.     */
  1324.     
  1325.     function getURL()
  1326.     {
  1327.         return $this->getMeta('URL') . $this->getValue('URL', 0, 0);
  1328.     }
  1329.     
  1330.     
  1331.     /**
  1332.     * 
  1333.     * Sets the value of the CLASS component.  There is only one allowed
  1334.     * per vCard.
  1335.     *
  1336.     * @access public
  1337.     * 
  1338.     * @param string $text The value to set for this component.
  1339.     *
  1340.     * @return void
  1341.     * 
  1342.     */
  1343.     
  1344.     function setClass($text)
  1345.     {
  1346.         $this->autoparam = 'CLASS';
  1347.         $this->setValue('CLASS', 0, 0, $text);
  1348.     }
  1349.     
  1350.     
  1351.     /**
  1352.     * 
  1353.     * Gets back the value of the CLASS component.  There is only one
  1354.     * allowed per vCard.
  1355.     *
  1356.     * @access public
  1357.     * 
  1358.     * @return string The value of this component.
  1359.     * 
  1360.     */
  1361.     
  1362.     function getClass()
  1363.     {
  1364.         return $this->getMeta('CLASS') .
  1365.             $this->getValue('CLASS', 0, 0);
  1366.     }
  1367.     
  1368.     
  1369.     /**
  1370.     * 
  1371.     * Sets the value of the SORT-STRING component.  There is only one
  1372.     * allowed per vCard.
  1373.     *
  1374.     * @access public
  1375.     * 
  1376.     * @param string $text The value to set for this component.
  1377.     *
  1378.     * @return void
  1379.     * 
  1380.     */
  1381.     
  1382.     function setSortString($text)
  1383.     {
  1384.         $this->autoparam = 'SORT-STRING';
  1385.         $this->setValue('SORT-STRING', 0, 0, $text);
  1386.     }
  1387.     
  1388.     
  1389.     /**
  1390.     * 
  1391.     * Gets back the value of the SORT-STRING component.  There is only
  1392.     * one allowed per vCard.
  1393.     * 
  1394.     * @access public
  1395.     * 
  1396.     * @return string The value of this component.
  1397.     * 
  1398.     */
  1399.     
  1400.     function getSortString()
  1401.     {
  1402.         return $this->getMeta('SORT-STRING') .
  1403.             $this->getValue('SORT-STRING', 0, 0);
  1404.     }
  1405.     
  1406.     
  1407.     /**
  1408.     * 
  1409.     * Sets the value of the PRODID component.  There is only one allowed
  1410.     * per vCard.
  1411.     * 
  1412.     * @access public
  1413.     * 
  1414.     * @param string $text The value to set for this component.
  1415.     * 
  1416.     * @return void
  1417.     * 
  1418.     */
  1419.     
  1420.     function setProductID($text)
  1421.     {
  1422.         $this->autoparam = 'PRODID';
  1423.         $this->setValue('PRODID', 0, 0, $text);
  1424.     }
  1425.     
  1426.     
  1427.     /**
  1428.     * 
  1429.     * Gets back the value of the PRODID component.  There is only one
  1430.     * allowed per vCard.
  1431.     * 
  1432.     * @access public
  1433.     * 
  1434.     * @return string The value of this component.
  1435.     * 
  1436.     */
  1437.     
  1438.     function getProductID()
  1439.     {
  1440.         return $this->getMeta('PRODID') .
  1441.             $this->getValue('PRODID', 0, 0);
  1442.     }
  1443.     
  1444.     
  1445.     
  1446.     
  1447.     /**
  1448.     * 
  1449.     * Sets the value of the REV component.  There is only one allowed
  1450.     * per vCard.
  1451.     * 
  1452.     * @access public
  1453.     * 
  1454.     * @param string $text The value to set for this component.
  1455.     * 
  1456.     * @return void
  1457.     * 
  1458.     */
  1459.     
  1460.     function setRevision($text)
  1461.     {
  1462.         $this->autoparam = 'REV';
  1463.         $this->setValue('REV', 0, 0, $text);
  1464.     }
  1465.     
  1466.     
  1467.     /**
  1468.     * 
  1469.     * Gets back the value of the REV component.  There is only one
  1470.     * allowed per vCard.
  1471.     * 
  1472.     * @access public
  1473.     * 
  1474.     * @return string The value of this component.
  1475.     * 
  1476.     */
  1477.     
  1478.     function getRevision()
  1479.     {
  1480.         return $this->getMeta('REV') . $this->getValue('REV', 0, 0);
  1481.     }
  1482.     
  1483.     
  1484.     /**
  1485.     * 
  1486.     * Sets the value of the UID component.  There is only one allowed
  1487.     * per vCard.
  1488.     * 
  1489.     * @access public
  1490.     * 
  1491.     * @param string $text The value to set for this component.
  1492.     * 
  1493.     * @return void
  1494.     * 
  1495.     */
  1496.     
  1497.     function setUniqueID($text)
  1498.     {
  1499.         $this->autoparam = 'UID';
  1500.         $this->setValue('UID', 0, 0, $text);
  1501.     }
  1502.     
  1503.     
  1504.     /**
  1505.     * 
  1506.     * Gets back the value of the UID component.  There is only one
  1507.     * allowed per vCard.
  1508.     * 
  1509.     * @access public
  1510.     * 
  1511.     * @return string The value of this component.
  1512.     * 
  1513.     */
  1514.     
  1515.     function getUniqueID()
  1516.     {
  1517.         return $this->getMeta('UID') . $this->getValue('UID', 0, 0);
  1518.     }
  1519.     
  1520.     
  1521.     /**
  1522.     * 
  1523.     * Sets the value of the AGENT component.  There is only one allowed
  1524.     * per vCard.
  1525.     * 
  1526.     * @access public
  1527.     * 
  1528.     * @param string $text The value to set for this component.
  1529.     * 
  1530.     * @return void
  1531.     * 
  1532.     */
  1533.     
  1534.     function setAgent($text)
  1535.     {
  1536.         $this->autoparam = 'AGENT';
  1537.         $this->setValue('AGENT', 0, 0, $text);
  1538.     }
  1539.     
  1540.     
  1541.     /**
  1542.     * 
  1543.     * Gets back the value of the AGENT component.  There is only one
  1544.     * allowed per vCard.
  1545.     * 
  1546.     * @access public
  1547.     * 
  1548.     * @return string The value of this component.
  1549.     * 
  1550.     */
  1551.     
  1552.     function getAgent()
  1553.     {
  1554.         return $this->getMeta('AGENT') .
  1555.             $this->getValue('AGENT', 0, 0);
  1556.     }
  1557.     
  1558.     
  1559.     /**
  1560.     * 
  1561.     * Sets the value of both parts of the GEO component.  There is only
  1562.     * one GEO component allowed per vCard.
  1563.     * 
  1564.     * @access public
  1565.     * 
  1566.     * @param string $lat The value to set for the longitude part
  1567.     * (decimal, + or -).
  1568.     * 
  1569.     * @param string $lon The value to set for the latitude part
  1570.     * (decimal, + or -).
  1571.     * 
  1572.     * @return void
  1573.     * 
  1574.     */
  1575.     
  1576.     function setGeo($lat, $lon)
  1577.     {
  1578.         $this->autoparam = 'GEO';
  1579.         $this->setValue('GEO', 0, VCARD_GEO_LAT, $lat);
  1580.         $this->setValue('GEO', 0, VCARD_GEO_LON, $lon);
  1581.     }
  1582.     
  1583.     
  1584.     /**
  1585.     * 
  1586.     * Gets back the value of the GEO component.  There is only one
  1587.     * allowed per vCard.
  1588.     *
  1589.     * @access public
  1590.     * 
  1591.     * @return string The value of this component.
  1592.     * 
  1593.     */
  1594.     
  1595.     function getGeo()
  1596.     {
  1597.         return $this->getMeta('GEO', 0) .
  1598.             $this->getValue('GEO', 0, VCARD_GEO_LAT, 0) . ';' .
  1599.             $this->getValue('GEO', 0, VCARD_GEO_LON, 0);
  1600.     }
  1601.     
  1602.     
  1603.     /**
  1604.     * 
  1605.     * Sets the value of one entire ADR iteration.  There can be zero,
  1606.     * one, or more ADR components in a vCard.
  1607.     *
  1608.     * @access public
  1609.     * 
  1610.     * @param mixed $pob String (one repetition) or array (multiple
  1611.     * reptitions) of the p.o. box part of the ADR component iteration.
  1612.     * 
  1613.     * @param mixed $extend String (one repetition) or array (multiple
  1614.     * reptitions) of the "extended address" part of the ADR component
  1615.     * iteration.
  1616.     * 
  1617.     * @param mixed $street String (one repetition) or array (multiple
  1618.     * reptitions) of the street address part of the ADR component
  1619.     * iteration.
  1620.     * 
  1621.     * @param mixed $locality String (one repetition) or array (multiple
  1622.     * reptitions) of the locailty (e.g., city) part of the ADR component
  1623.     * iteration.
  1624.     * 
  1625.     * @param mixed $region String (one repetition) or array (multiple
  1626.     * reptitions) of the region (e.g., state, province, or governorate)
  1627.     * part of the ADR component iteration.
  1628.     * 
  1629.     * @param mixed $postcode String (one repetition) or array (multiple
  1630.     * reptitions) of the postal code (e.g., ZIP code) part of the ADR
  1631.     * component iteration.
  1632.     * 
  1633.     * @param mixed $country String (one repetition) or array (multiple
  1634.     * reptitions) of the country-name part of the ADR component
  1635.     * iteration.
  1636.     * 
  1637.     * @return void
  1638.     * 
  1639.     */
  1640.     
  1641.     function addAddress($pob, $extend, $street, $locality, $region,
  1642.         $postcode, $country)
  1643.     {
  1644.         $this->autoparam = 'ADR';
  1645.         $iter = $this->countIter('ADR');
  1646.         $this->setValue('ADR', $iter, VCARD_ADR_POB,       $pob);
  1647.         $this->setValue('ADR', $iter, VCARD_ADR_EXTEND,    $extend);
  1648.         $this->setValue('ADR', $iter, VCARD_ADR_STREET,    $street);
  1649.         $this->setValue('ADR', $iter, VCARD_ADR_LOCALITY,  $locality);
  1650.         $this->setValue('ADR', $iter, VCARD_ADR_REGION,    $region);
  1651.         $this->setValue('ADR', $iter, VCARD_ADR_POSTCODE,  $postcode);
  1652.         $this->setValue('ADR', $iter, VCARD_ADR_COUNTRY,   $country);
  1653.     }
  1654.     
  1655.     
  1656.     /**
  1657.     * 
  1658.     * Gets back the value of one ADR component iteration.
  1659.     *
  1660.     * @access public
  1661.     * 
  1662.     * @param int $iter The component iteration-number to get the value
  1663.     * for.
  1664.     * 
  1665.     * @return mixed The value of this component iteration, or a
  1666.     * PEAR_Error if the iteration is not valid.
  1667.     * 
  1668.     */
  1669.     
  1670.     function getAddress($iter)
  1671.     {
  1672.         if (! is_integer($iter) || $iter < 0) {
  1673.             
  1674.             return $this->raiseError('ADR iteration number not valid.');
  1675.         
  1676.         } else {
  1677.             
  1678.             return $this->getMeta('ADR', $iter) .
  1679.                 $this->getValue('ADR', $iter, VCARD_ADR_POB) . ';' .
  1680.                 $this->getValue('ADR', $iter, VCARD_ADR_EXTEND) . ';' .
  1681.                 $this->getValue('ADR', $iter, VCARD_ADR_STREET) . ';' .
  1682.                 $this->getValue('ADR', $iter, VCARD_ADR_LOCALITY) . ';' .
  1683.                 $this->getValue('ADR', $iter, VCARD_ADR_REGION) . ';' .
  1684.                 $this->getValue('ADR', $iter, VCARD_ADR_POSTCODE) . ';' .
  1685.                 $this->getValue('ADR', $iter, VCARD_ADR_COUNTRY);
  1686.         }
  1687.     }
  1688.     
  1689.     
  1690.     /**
  1691.     * 
  1692.     * Sets the value of one LABEL component iteration.  There can be
  1693.     * zero, one, or more component iterations in a vCard.
  1694.     *
  1695.     * @access public
  1696.     * 
  1697.     * @param string $text The value to set for this component.
  1698.     *
  1699.     * @return void
  1700.     * 
  1701.     */
  1702.     
  1703.     function addLabel($text)
  1704.     {
  1705.         $this->autoparam = 'LABEL';
  1706.         $iter = $this->countIter('LABEL');
  1707.         $this->setValue('LABEL', $iter, 0, $text);
  1708.     }
  1709.     
  1710.     
  1711.     /**
  1712.     * 
  1713.     * Gets back the value of one iteration of the LABEL component. 
  1714.     * There can be zero, one, or more component iterations in a vCard.
  1715.     *
  1716.     * @access public
  1717.     * 
  1718.     * @param int $iter The component iteration-number to get the value
  1719.     * for.
  1720.     *
  1721.     * @return mixed The value of this component, or a PEAR_Error if
  1722.     * the iteration number is not valid.
  1723.     * 
  1724.     */
  1725.     
  1726.     function getLabel($iter)
  1727.     {
  1728.         if (! is_integer($iter) || $iter < 0) {
  1729.             return $this->raiseError('LABEL iteration number not valid.');
  1730.         } else {
  1731.             return $this->getMeta('LABEL', $iter) .
  1732.                 $this->getValue('LABEL', $iter, 0);
  1733.         }
  1734.     }
  1735.     
  1736.     
  1737.     /**
  1738.     * 
  1739.     * Sets the value of one TEL component iteration.  There can be zero,
  1740.     * one, or more component iterations in a vCard.
  1741.     *
  1742.     * @access public
  1743.     * 
  1744.     * @param string $text The value to set for this component.
  1745.     *
  1746.     * @return void
  1747.     * 
  1748.     */
  1749.     
  1750.     function addTelephone($text)
  1751.     {
  1752.         $this->autoparam = 'TEL';
  1753.         $iter = $this->countIter('TEL');
  1754.         $this->setValue('TEL', $iter, 0, $text);
  1755.     }
  1756.     
  1757.     
  1758.     /**
  1759.     * 
  1760.     * Gets back the value of one iteration of the TEL component.  There
  1761.     * can be zero, one, or more component iterations in a vCard.
  1762.     *
  1763.     * @access public
  1764.     * 
  1765.     * @param int $iter The component iteration-number to get the value
  1766.     * for.
  1767.     *
  1768.     * @return mixed The value of this component, or a PEAR_Error if the
  1769.     * iteration number is not valid.
  1770.     * 
  1771.     */
  1772.     
  1773.     function getTelephone($iter)
  1774.     {
  1775.         if (! is_integer($iter) || $iter < 0) {
  1776.             return $this->raiseError('TEL iteration number not valid.');
  1777.         } else {
  1778.             return $this->getMeta('TEL', $iter) .
  1779.                 $this->getValue('TEL', $iter, 0);
  1780.         }
  1781.     }
  1782.     
  1783.     /**
  1784.     * 
  1785.     * Sets the value of one EMAIL component iteration.  There can be zero,
  1786.     * one, or more component iterations in a vCard.
  1787.     *
  1788.     * @access public
  1789.     * 
  1790.     * @param string $text The value to set for this component.
  1791.     *
  1792.     * @return void
  1793.     * 
  1794.     */
  1795.     
  1796.     function addEmail($text)
  1797.     {
  1798.         $this->autoparam = 'EMAIL';
  1799.         $iter = $this->countIter('EMAIL');
  1800.         $this->setValue('EMAIL', $iter, 0, $text);
  1801.     }
  1802.     
  1803.     
  1804.     /**
  1805.     * 
  1806.     * Gets back the value of one iteration of the EMAIL component.  There can
  1807.     * be zero, one, or more component iterations in a vCard.
  1808.     *
  1809.     * @access public
  1810.     * 
  1811.     * @param int $iter The component iteration-number to get the value
  1812.     * for.
  1813.     *
  1814.     * @return mixed The value of this component, or a PEAR_Error if the
  1815.     * iteration number is not valid.
  1816.     * 
  1817.     */
  1818.     
  1819.     function getEmail($iter)
  1820.     {
  1821.         if (! is_integer($iter) || $iter < 0) {
  1822.             return $this->raiseError('EMAIL iteration number not valid.');
  1823.         } else {
  1824.             return $this->getMeta('EMAIL', $iter) .
  1825.                 $this->getValue('EMAIL', $iter, 0);
  1826.         }
  1827.     }
  1828.     
  1829.     
  1830.     /**
  1831.     * 
  1832.     * Sets the full value of the NICKNAME component.  There is only one
  1833.     * component iteration allowed per vCard, but there may be multiple
  1834.     * value repetitions in the iteration.
  1835.     *
  1836.     * @access public
  1837.     * 
  1838.     * @param mixed $text String (one repetition) or array (multiple
  1839.     * reptitions) of the component iteration value.
  1840.     *
  1841.     * @return void
  1842.     * 
  1843.     */
  1844.     
  1845.     function addNickname($text)
  1846.     {
  1847.         $this->autoparam = 'NICKNAME';
  1848.         $this->addValue('NICKNAME', 0, 0, $text);
  1849.     }
  1850.     
  1851.     
  1852.     /**
  1853.     * 
  1854.     * Gets back the value of the NICKNAME component.  There is only one
  1855.     * component allowed per vCard, but there may be multiple value
  1856.     * repetitions in the iteration.
  1857.     *
  1858.     * @access public
  1859.     * 
  1860.     * @return string The value of this component.
  1861.     * 
  1862.     */
  1863.     
  1864.     function getNickname()
  1865.     {
  1866.         return $this->getMeta('NICKNAME') .
  1867.             $this->getValue('NICKNAME', 0, 0);
  1868.     }
  1869.     
  1870.     
  1871.     
  1872.     /**
  1873.     * 
  1874.     * Sets the full value of the CATEGORIES component.  There is only
  1875.     * one component iteration allowed per vCard, but there may be
  1876.     * multiple value repetitions in the iteration.
  1877.     *
  1878.     * @access public
  1879.     * 
  1880.     * @param mixed $text String (one repetition) or array (multiple
  1881.     * reptitions) of the component iteration value.
  1882.     *
  1883.     * @return void
  1884.     * 
  1885.     */
  1886.     
  1887.     function addCategories($text, $append = true)
  1888.     {
  1889.         $this->autoparam = 'CATEGORIES';
  1890.         $this->addValue('CATEGORIES', 0, 0, $text);
  1891.     }
  1892.     
  1893.     
  1894.     /**
  1895.     * 
  1896.     * Gets back the value of the CATEGORIES component.  There is only
  1897.     * one component allowed per vCard, but there may be multiple value
  1898.     * repetitions in the iteration.
  1899.     *
  1900.     * @access public
  1901.     * 
  1902.     * @return string The value of this component.
  1903.     * 
  1904.     */
  1905.     
  1906.     function getCategories()
  1907.     {
  1908.         return $this->getMeta('CATEGORIES', 0) .
  1909.             $this->getValue('CATEGORIES', 0, 0);
  1910.     }
  1911.     
  1912.     
  1913.     /**
  1914.     * 
  1915.     * Sets the full value of the ORG component.  There can be only one
  1916.     * ORG component in a vCard.
  1917.     * 
  1918.     * The ORG component can have one or more parts (as opposed to
  1919.     * repetitions of values within those parts).  The first part is the
  1920.     * highest-level organization, the second part is the next-highest,
  1921.     * the third part is the third-highest, and so on.  There can by any
  1922.     * number of parts in one ORG iteration.  (This is different from
  1923.     * other components, such as NICKNAME, where an iteration has only
  1924.     * one part but may have many repetitions within that part.)
  1925.     * 
  1926.     * @access public
  1927.     * 
  1928.     * @param mixed $text String (one ORG part) or array (of ORG
  1929.     * parts) to use as the value for the component iteration.
  1930.     * 
  1931.     * @return void
  1932.     * 
  1933.     */
  1934.     
  1935.     function addOrganization($text)
  1936.     {
  1937.         $this->autoparam = 'ORG';
  1938.         
  1939.         settype($text, 'array');
  1940.         
  1941.         $base = $this->countRept('ORG', 0);
  1942.         
  1943.         // start at the original base point, and add
  1944.         // new parts
  1945.         foreach ($text as $part => $val) {
  1946.             $this->setValue('ORG', 0, $base + $part, $val);
  1947.         }
  1948.     }
  1949.     
  1950.     
  1951.     /**
  1952.     * 
  1953.     * Gets back the value of the ORG component.
  1954.     * 
  1955.     * @return string The value of this component.
  1956.     * 
  1957.     */
  1958.     
  1959.     function getOrganization()
  1960.     {
  1961.         $text = $this->getMeta('ORG', 0);
  1962.         
  1963.         $k = $this->countRept('ORG', 0);
  1964.         $last = $k - 1;
  1965.         
  1966.         for ($part = 0; $part < $k; $part++) {
  1967.         
  1968.             $text .= $this->getValue('ORG', 0, $part);
  1969.             
  1970.             if ($part != $last) {
  1971.                 $text .= ';';
  1972.             }
  1973.             
  1974.         }
  1975.         
  1976.         return $text;
  1977.     }
  1978.     
  1979.     
  1980.     /**
  1981.     * 
  1982.     * Builds a vCard from a Contact_Vcard_Parse result array.  Only send
  1983.     * one vCard from the parse-results.
  1984.     *
  1985.     * Usage (to build from first vCard in parsed results):
  1986.     * 
  1987.     * $parse = new Contact_Vcard_Parse(); // new parser
  1988.     * $info = $parse->fromFile('sample.vcf'); // parse file
  1989.     * 
  1990.     * $vcard = new Contact_Vcard_Build(); // new builder
  1991.     * $vcard->setFromArray($info[0]); // [0] is the first card
  1992.     * 
  1993.     * 
  1994.     * @access public
  1995.     * 
  1996.     * @param array $src One vCard entry as parsed using
  1997.     * Contact_Vcard_Parse.
  1998.     * 
  1999.     * @return void
  2000.     * 
  2001.     * @see Contact_Vcard_Parse::fromFile()
  2002.     * 
  2003.     * @see Contact_Vcard_Parse::fromText()
  2004.     * 
  2005.     */
  2006.     
  2007.     function setFromArray($src)
  2008.     {
  2009.         // reset to a blank values and params
  2010.         $this->value = array();
  2011.         $this->param = array();
  2012.         
  2013.         // loop through components (N, ADR, TEL, etc)
  2014.         foreach ($src AS $comp => $comp_val) {
  2015.             
  2016.             // set the autoparam property. not really needed, but let's
  2017.             // behave after an expected fashion, shall we?  ;-)
  2018.             $this->autoparam = $comp; 
  2019.             
  2020.             // iteration number of each component
  2021.             foreach ($comp_val AS $iter => $iter_val) {
  2022.                 
  2023.                 // value or param?
  2024.                 foreach ($iter_val AS $kind => $kind_val) {
  2025.                 
  2026.                     // part number
  2027.                     foreach ($kind_val AS $part => $part_val) {
  2028.                         
  2029.                         // repetition number and text value
  2030.                         foreach ($part_val AS $rept => $text) {
  2031.                             
  2032.                             // ignore data when $kind is neither 'value'
  2033.                             // nor 'param'
  2034.                             if (strtolower($kind) == 'value') {
  2035.                                 $this->value[strtoupper($comp)][$iter][$part][$rept] = $text;
  2036.                             } elseif (strtolower($kind) == 'param') {
  2037.                                 $this->param[strtoupper($comp)][$iter][$part][$rept] = $text;
  2038.                             }
  2039.                             
  2040.                         }
  2041.                     }
  2042.                 }
  2043.             }
  2044.         }
  2045.     }
  2046.     
  2047.     
  2048.     /**
  2049.     *
  2050.     * Fetches a full vCard text block based on $this->value and
  2051.     * $this->param. The order of the returned components is similar to
  2052.     * their order in RFC 2426.  Honors the value of
  2053.     * $this->value['VERSION'] to determine which vCard components are
  2054.     * returned (2.1- or 3.0-compliant).
  2055.     *
  2056.     * @access public
  2057.     * 
  2058.     * @return string A properly formatted vCard text block.
  2059.     *
  2060.     */
  2061.     
  2062.     function fetch()
  2063.     {
  2064.         // vCard version is required
  2065.         if (! is_array($this->value['VERSION'])) {
  2066.             return $this->raiseError('VERSION not set (required).');
  2067.         }
  2068.         
  2069.         // FN component is required
  2070.         if (! is_array($this->value['FN'])) {
  2071.             return $this->raiseError('FN component not set (required).');
  2072.         }
  2073.         
  2074.         // N component is required
  2075.         if (! is_array($this->value['N'])) {
  2076.             return $this->raiseError('N component not set (required).');
  2077.         }
  2078.         
  2079.         // initialize the vCard lines
  2080.         $lines = array();
  2081.         
  2082.         // begin (required)
  2083.         $lines[] = "BEGIN:VCARD";
  2084.         
  2085.         // version (required)
  2086.         // available in both 2.1 and 3.0
  2087.         $lines[] = $this->getVersion();
  2088.         
  2089.         // formatted name (required)
  2090.         // available in both 2.1 and 3.0
  2091.         $lines[] = $this->getFormattedName();
  2092.         
  2093.         // structured name (required)
  2094.         // available in both 2.1 and 3.0
  2095.         $lines[] = $this->getName();
  2096.         
  2097.         // profile (3.0 only)
  2098.         if ($this->value['VERSION'][0][0][0] == '3.0') {
  2099.             $lines[] = "PROFILE:VCARD";
  2100.         }
  2101.         
  2102.         // displayed name of the data source  (3.0 only)
  2103.         if (isset($this->value['NAME']) &&
  2104.             $this->value['VERSION'][0][0][0] == '3.0') {
  2105.             $lines[] = $this->getSourceName();
  2106.         }
  2107.         
  2108.         // data source (3.0 only)
  2109.         if (isset($this->value['SOURCE']) &&
  2110.             $this->value['VERSION'][0][0][0] == '3.0') {
  2111.             $lines[] = $this->getSource();
  2112.         }
  2113.         
  2114.         // nicknames (3.0 only)
  2115.         if (isset($this->value['NICKNAME']) &&
  2116.             $this->value['VERSION'][0][0][0] == '3.0') {
  2117.             $lines[] = $this->getNickname();
  2118.         }
  2119.         
  2120.         // personal photo
  2121.         // available in both 2.1 and 3.0
  2122.         if (isset($this->value['PHOTO'])) {
  2123.             $lines[] = $this->getPhoto();
  2124.         }
  2125.         
  2126.         // bday
  2127.         // available in both 2.1 and 3.0
  2128.         if (isset($this->value['BDAY'])) {
  2129.             $lines[] = $this->getBirthday();
  2130.         }
  2131.         
  2132.         // adr
  2133.         // available in both 2.1 and 3.0
  2134.         if (isset($this->value['ADR'])) {
  2135.             foreach ($this->value['ADR'] as $key => $val) {
  2136.                 $lines[] = $this->getAddress($key);
  2137.             }
  2138.         }
  2139.         
  2140.         // label
  2141.         // available in both 2.1 and 3.0
  2142.         if (isset($this->value['LABEL'])) {
  2143.             foreach ($this->value['LABEL'] as $key => $val) {
  2144.                 $lines[] = $this->getLabel($key);
  2145.             }
  2146.         }
  2147.         
  2148.         // tel
  2149.         // available in both 2.1 and 3.0
  2150.         if (isset($this->value['TEL'])) {
  2151.             foreach ($this->value['TEL'] as $key => $val) {
  2152.                 $lines[] = $this->getTelephone($key);
  2153.             }
  2154.         }
  2155.         
  2156.         // email
  2157.         // available in both 2.1 and 3.0
  2158.         if (isset($this->value['EMAIL'])) {
  2159.             foreach ($this->value['EMAIL'] as $key => $val) {
  2160.                 $lines[] = $this->getEmail($key);
  2161.             }
  2162.         }
  2163.         
  2164.         // mailer
  2165.         // available in both 2.1 and 3.0
  2166.         if (isset($this->value['MAILER'])) {
  2167.             $lines[] = $this->getMailer();
  2168.         }
  2169.         
  2170.         // tz
  2171.         // available in both 2.1 and 3.0
  2172.         if (isset($this->value['TZ'])) {
  2173.             $lines[] = $this->getTZ();
  2174.         }
  2175.         
  2176.         // geo
  2177.         // available in both 2.1 and 3.0
  2178.         if (isset($this->value['GEO'])) {
  2179.             $lines[] = $this->getGeo();
  2180.         }
  2181.         
  2182.         // title
  2183.         // available in both 2.1 and 3.0
  2184.         if (isset($this->value['TITLE'])) {
  2185.             $lines[] = $this->getTitle();
  2186.         }
  2187.         
  2188.         // role
  2189.         // available in both 2.1 and 3.0
  2190.         if (isset($this->value['ROLE'])) {
  2191.             $lines[] = $this->getRole();
  2192.         }
  2193.         
  2194.         // company logo
  2195.         // available in both 2.1 and 3.0
  2196.         if (isset($this->value['LOGO'])) {
  2197.             $lines[] = $this->getLogo();
  2198.         }
  2199.         
  2200.         // agent
  2201.         // available in both 2.1 and 3.0
  2202.         if (isset($this->value['AGENT'])) {
  2203.             $lines[] = $this->getAgent();
  2204.         }
  2205.         
  2206.         // org
  2207.         // available in both 2.1 and 3.0
  2208.         if (isset($this->value['ORG'])) {
  2209.             $lines[] = $this->getOrganization();
  2210.         }
  2211.         
  2212.         // categories (3.0 only)
  2213.         if (isset($this->value['CATEGORIES']) &&
  2214.             $this->value['VERSION'][0][0][0] == '3.0') {
  2215.             $lines[] = $this->getCategories();
  2216.         }
  2217.         
  2218.         // note
  2219.         // available in both 2.1 and 3.0
  2220.         if (isset($this->value['NOTE'])) {
  2221.             $lines[] = $this->getNote();
  2222.         }
  2223.         
  2224.         // prodid (3.0 only)
  2225.         if (isset($this->value['PRODID']) &&
  2226.             $this->value['VERSION'][0][0][0] == '3.0') {
  2227.             $lines[] = $this->getProductID();
  2228.         }
  2229.         
  2230.         // rev
  2231.         // available in both 2.1 and 3.0
  2232.         if (isset($this->value['REV'])) {
  2233.             $lines[] = $this->getRevision();
  2234.         }
  2235.         
  2236.         // sort-string (3.0 only)
  2237.         if (isset($this->value['SORT-STRING']) &&
  2238.             $this->value['VERSION'][0][0][0] == '3.0') {
  2239.             $lines[] = $this->getSortString();
  2240.         }
  2241.         
  2242.         // name-pronounciation sound
  2243.         // available in both 2.1 and 3.0
  2244.         if (isset($this->value['SOUND'])) {
  2245.             $lines[] = $this->getSound();
  2246.         }
  2247.         
  2248.         // uid
  2249.         // available in both 2.1 and 3.0
  2250.         if (isset($this->value['UID'])) {
  2251.             $lines[] = $this->getUniqueID();
  2252.         }
  2253.         
  2254.         // url
  2255.         // available in both 2.1 and 3.0
  2256.         if (isset($this->value['URL'])) {
  2257.             $lines[] = $this->getURL();
  2258.         }
  2259.         
  2260.         // class (3.0 only)
  2261.         if (isset($this->value['CLASS']) &&
  2262.             $this->value['VERSION'][0][0][0] == '3.0') {
  2263.             $lines[] = $this->getClass();
  2264.         }
  2265.         
  2266.         // key
  2267.         // available in both 2.1 and 3.0
  2268.         if (isset($this->value['KEY'])) {
  2269.             $lines[] = $this->getKey();
  2270.         }
  2271.         
  2272.         // required
  2273.         $lines[] = "END:VCARD";
  2274.         
  2275.         // version 3.0 uses \n for new lines,
  2276.         // version 2.1 uses \r\n
  2277.         $newline = "\n";
  2278.         if ($this->value['VERSION'][0][0][0] == '2.1') {
  2279.             $newline = "\r\n";
  2280.         }
  2281.         
  2282.         // fold lines at 75 characters
  2283.         $regex = "(.{1,75})";
  2284.            foreach ($lines as $key => $val) {
  2285.             if (strlen($val) > 75) {
  2286.                 // we trim to drop the last newline, which will be added
  2287.                 // again by the implode function at the end of fetch()
  2288.                 $lines[$key] = trim(preg_replace("/$regex/i", "\\1$newline ", $val));
  2289.             }
  2290.         }
  2291.         
  2292.         // compile the array of lines into a single text block
  2293.         // and return (with a trailing newline)
  2294.         return implode($newline, $lines). $newline;
  2295.     }
  2296.     
  2297.  
  2298.     /**
  2299.     *
  2300.     * Send the vCard as a downloadable file.
  2301.     *
  2302.     * @access public
  2303.     * 
  2304.     * @param string $filename The file name to give the vCard.
  2305.     *
  2306.     * @param string $disposition How the file should be sent, either
  2307.     * 'inline' or 'attachment'.
  2308.     * 
  2309.     * @param string $charset The character set to use, defaults to
  2310.     * 'us-ascii'.
  2311.     * 
  2312.     * @return void
  2313.     * 
  2314.     */
  2315.     
  2316.     function send($filename, $disposition = 'attachment',
  2317.         $charset = 'us-ascii')
  2318.     {
  2319.         $vcard = $this->fetch();
  2320.         
  2321.         header(
  2322.             'Content-Type: application/directory; ' . 
  2323.             'profile="vcard"; ' .
  2324.             'charset=' . $charset
  2325.         );
  2326.             
  2327.         header('Content-Length: ' . strlen($vcard));
  2328.         header("Content-Disposition: $disposition; filename=\"$filename\"");
  2329.         
  2330.         echo $vcard;
  2331.     }
  2332.     
  2333.  
  2334.     /**
  2335.     *
  2336.     * Count the number of iterations for an element type.
  2337.     *
  2338.     * @access public
  2339.     * 
  2340.     * @param string $type The element type to count iterations for
  2341.     * (ADR, ORG, etc).
  2342.     *
  2343.     * @return int The number of iterations for that type.
  2344.     * 
  2345.     */
  2346.     
  2347.     function countIter($type)
  2348.     {
  2349.         if (!isset($this->value[$type])) {
  2350.             return 0;
  2351.         } else {
  2352.             return count($this->value[$type]);
  2353.         }
  2354.     }
  2355.     
  2356.  
  2357.     /**
  2358.     *
  2359.     * Count the number of repetitions for an element type and iteration
  2360.     * number.
  2361.     *
  2362.     * @access public
  2363.     * 
  2364.     * @param string $type The element type to count iterations for
  2365.     * (ADR, ORG, etc).
  2366.     *
  2367.     * @param int $iter The iteration number to count repetitions for.
  2368.     *
  2369.     * @return int The number of repetitions for that type and iteration.
  2370.     * 
  2371.     */
  2372.     
  2373.     function countRept($type, $rept)
  2374.     {
  2375.         if (!isset($this->value[$type][$rept])) {
  2376.             return 0;
  2377.         } else {
  2378.             return count($this->value[$type][$rept]);
  2379.         }
  2380.     }
  2381.     
  2382.     
  2383.     /**
  2384.     *
  2385.     * Emulated destructor.
  2386.     *
  2387.     * @access private
  2388.     * 
  2389.     * @return boolean true
  2390.     *
  2391.     */
  2392.     
  2393.     function _Contact_Vcard_Build()
  2394.     {
  2395.         return true;
  2396.     }
  2397. }
  2398.  
  2399. ?>